//
//  Closure.swift
//  Swift_base_grammar
//
//  Created by lantaiyuan on 2017/9/13.
//  Copyright © 2017年 lantaiyuan. All rights reserved.
//  10--闭包操作

import Foundation
import UIKit

/**
 闭包 - 类似 OC 中的 block
 block
 - 是一组预先准备好的代码，在需要的时候执行
 - 可以当作参数传递
 - 如果出现 self 需要注意循环引用
 */

// 定义闭包 --在 Swift 中，函数本身就可以当作参数传递
/**
 1. 闭包的所有代码[参数 返回值 执行代码]都放在 {} 中
 2. in 是用来区分函数定义和执行代码
 
 格式
 {
 (parameters) -> returnType in
  statements
 }
 */
public let sumFunc:(Int,Int) ->(Int) = {
    (a:Int,b:Int) -> Int in
    return a + b
}

//Swift可以根据闭包上下文推断参数和返回值的类型，所以上面的例子可以简化如下
public let sumFunc2:(Int,Int) ->(Int) = {
   a,b in
   return a + b
}

//单行表达式闭包可以隐式返回，如下，省略return
public let sumFunc3:(Int,Int) ->(Int) = { a,b in  a + b}

//如果闭包没有参数，可以直接省略“in”
public let sumFunc4:() ->Int = { return 100 + 120 }

//这个是既没有参数也没返回值，所以把return和in都省略了
public let sumFunc5:() ->Void = { print("该拨打119了") }

// 外部参数在定义 闭包的时候非常重要，能够有智能提示
typealias sumFuncBlock = (Int,Int) ->Int
let sumFunc6:sumFuncBlock = {
  (a,b) in a + b
}

let funcDemo = {
    print("`简单`的闭包，如果没有参数和返回值，参数/返回值/in 都可以省略")
}

// block / 闭包的应用场景
// 1.通常用在异步加载网络数据，完成回调
func loadData(finish:@escaping () ->()) {
    DispatchQueue.global().async { 
        print("耗时操作\(Thread.current)")
        
        //数据加载完  block回调
        DispatchQueue.main.async {
            print("完成\(Thread.current)")
            //执行finish回调
            finish()
        }
    }
}

//定义完成回调属性
//闭包属性可选optional
var finishedCallBack:( (_ html:String)->())?

//2. 通常用在异步加载网络数据，完成回调 －> 以 参数 的形式 传递网络获取的数据
func loadData2(finished:@escaping (_ html:String) ->()) {
    
    finishedCallBack = finished
    DispatchQueue.global().async {
        print("耗时操作\(Thread.current)")
        
        //数据加载完  block回调
        DispatchQueue.main.async {
            print("完成\(Thread.current)")
            
            finishedCallBack!("hahaha")
            //执行finish回调
            finished("<html></html>")
        }
    }
}

// `尾`随闭包 - 不要求自己写，但是，要求必须能看懂
// 1. 闭包最后一个参数
// 2. 函数 的 ) 前置到倒数第二个参数末尾
// 3. 最后一个逗号省略
// 补充，简化闭包，如果没有参数，没有返回值，可以省略
func loadData3() {
    DispatchQueue.global().async {
       print("haha")
    }
    DispatchQueue.global().async {
        print("hehe")
        
        DispatchQueue.main.sync {
            print("主线程回调")
        }
    }
}

/// 逃逸闭包
///
/// - Parameter closure: <#closure description#>
func myFunc(closure:@escaping(Int,Int) ->Bool) {
    
}
func myFunc2(closure:@autoclosure @escaping () ->Bool) {
    
}
